home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Safari 2.4.2 / Safari.c < prev    next >
Text File  |  1996-07-07  |  47KB  |  2,022 lines

  1. /* ----------------------------------------------------------------------
  2.  
  3.     Safari
  4.     version 2.4.2
  5.     
  6.     Written by: John Gallaugher
  7.     Ported to CW by: Paul Celestin
  8.     
  9.     This simple application does nothing but display a simple clock in
  10.     a rectangle on your display. You can move the clock around, and you
  11.     can also check the date by clicking once on the clock.
  12.     
  13.     941207 - 1.1.3 initial release
  14.     951215 - 2.4.1 updated for CW7
  15.     960704 - 2.4.2 updated for CW9
  16.  
  17. ---------------------------------------------------------------------- */
  18. /*
  19.     Code release for Safari II 1.1.3
  20.     Changes since 1.0 release:
  21.         It's now FREE! (please send comments & a postcard)
  22.         The sicn's were eliminated from the apple menu so it should now work on older systems
  23.         The dialog box in which I begged for a job is gone (I've found work, thanks!)
  24.         The option to 'score when hit' in rectangle surrounding animal now works.
  25.            
  26.     There still seems to be problems with the sound playing on older 68000 Macs.  Any advice on
  27.     this problem, or more descript diagnoses would be appreciated.
  28.  
  29.     SAFARI II © 1991 by John Gallaugher
  30.         A program written in Think C.  Portions copyright Symantec and Apple Computer.
  31.  
  32.     In 1985 I wrote a program called Safari to try to teach myself the Macintosh toolbox.  
  33.     The original Safari was simple and cute, but it was also a program which doesn't work on
  34.     today's machines.  Safari II is an update to the orginal Safari.  It should work on all
  35.     Macs with at least 1 meg of memory running system 6.0.x or greater.
  36.     
  37.     Although I have done quite a bit of Macintosh database development, I have never programmed
  38.     professioanlly in the toolbox or in C.  As such, please excuse the clumsiness of some of
  39.     this code.  I am distributing the source code and game for free in hopes that it will help
  40.     others learn some of the basics of Macintosh game development.  My experience has found that
  41.     there's not much free source code out there to help the would-be game developmer.  I hope my
  42.     modest submission helps some folks get started.
  43.     
  44.     Although this product is offerd for free, I DO ask those pros and semi-pros out there to
  45.     offer suggestions on how I can improve this code.  Since I'm pretty green in toolbox coding
  46.     I would greatly appreciate advice.  Please don't hold back,  criticize me to the hilt!  
  47.     I need and welcome the help.
  48.     
  49.     Also, please don't distribute any modified versions of Safari.  I welcome you to learn from
  50.     the code and encourage you to produce original work, but I would like all updates of the game
  51.     to pass through me.
  52.     
  53.     Lastly, please send comments!  I love to hear from folks who have received my game.  
  54.     My E-Mail addresses are:
  55.     CIS - 70137,763
  56.     AOL - GALLAUGHER
  57.     
  58.     If you'd care to send any U.S. Mail (I love postcards), forward
  59.     them to:
  60.         Safari
  61.         c/o John Gallaugher
  62.         Three Allegheny Center #118
  63.         Pittsburgh, PA 15212
  64.         
  65.     A special thanks to the helpful folks at the Boston Computer Society's MacTech group, and to
  66.     the outstanding faculty of the Boston College Computer Science Program for their patient help
  67.     in answering my silly questions.
  68.     
  69.     This program seems to work fine on my 4 meg LC running under System 7.0 if you run into any
  70.     problems, PLEASE let me know.
  71.     
  72.     RESOURCE NOTE:  All sounds were created using the microphone on a Macintosh LC.
  73.         All pictures were created using MacPaint.  The 'RGN ' resources which are used to detect
  74.         the boundries of the animal bodies were created using a utilty program called 'Regions'
  75.         created by the late Duane Blehm (it should be available via local user groups and on-line
  76.         services).  All other resources were created directly in ResEdit.
  77. */
  78.  
  79. #include <Sound.h> /* adds routines need to play Asynch Sound */
  80.  
  81. /*
  82.     sorry about any inconsistencies in declaring resource numbers.  I started
  83.     and stopped the project several times and added things on the fly without
  84.     thinking of a logical numbering system.  Feel free to suggest a convention.
  85. */
  86.  
  87. #define M_T_F                    ((void *) -1L) /* used in setting up windows */
  88. #define    BASE_RES_ID                400
  89. #define    REMOVE_ALL_EVENTS        0
  90.  
  91. #define    BORDER                    6  /* number of pixels between window and screen width */
  92. #define    TITLE_BAR_HEIGHT        19 /* I guessed, is there a TB call to get this? */
  93. #define    TICK_DELAY                1  /* this cycles the animation through 1 tick, or 1/60th of a second */
  94.  
  95. /* Menu IDs */
  96. #define    APPLE_MENU_ID            1
  97. #define    FILE_MENU_ID            401
  98. #define    EDIT_MENU_ID            402
  99. #define    GAME_MENU_ID            403
  100.  
  101. /* Menu Items */
  102. #define    ABOUT_ITEM                1
  103. #define    NEW_GAME_ITEM            1
  104. #define    PAUSE_RESUME_ITEM        2
  105. #define    STOP_ITEM                3
  106. #define    QUIT_ITEM                5
  107. #define    UNDO_ITEM                1
  108. #define    CUT_ITEM                3
  109. #define    COPY_ITEM                4
  110. #define    PASTE_ITEM                5
  111. #define    CLEAR_ITEM                6
  112. #define    GAME_OPTIONS_ITEM        1
  113. #define    ANIMAL_POINT_VALUES_ITEM    2
  114. #define    HALL_OF_FAME_ITEM        3
  115.  
  116. /* Alerts */
  117. #define    ERROR_ALERT_ID            401
  118. #define    ERROR_EDIT_TEXT            402
  119.  
  120. /* Dialogs */
  121. #define    GAME_OPTIONS_DIALOG        200
  122. #define    SAVE_HIGH_SCORES_DIALOG    300
  123. #define    ANIMAL_POINT_VALUES_DIALOG    129
  124. #define    INTRO_DIALOG            475
  125. #define    ABOUT_DIALOG            476
  126. #define    PLAYER_NAME_DIALOG        500
  127. #define    HALL_OF_FAME_DIALOG        550
  128.  
  129. /* Dialog Items */
  130. #define OK_BUTTON                1
  131. #define    SAVE_AND_CLEAR_BUTTON    2
  132. #define    CANCEL_BUTTON            3
  133. #define    TIMED_RADIO                4
  134. #define    ESCAPED_RADIO            5
  135. #define    NINE_INCH_RADIO            6
  136. #define    CURRENT_SCREEN_RADIO    7
  137. #define    INCREASE_YES_RADIO        8
  138. #define    INCREASE_NO_RADIO        9
  139. #define    IN_BOX_SURROUNDING_ANIMAL_RADIO    10
  140. #define    IN_ANIMAL_OUTLINE_RADIO    11
  141. #define    MINUTES                    12
  142. #define    SECONDS                    13
  143. #define    MAX_ESCAPED                14
  144. #define SPEED_POP_UP            15
  145. #define    SLOW_RADIO                25
  146. #define    MEDIUM_RADIO            26
  147. #define    FAST_RADIO                27
  148. #define    PLAYER_NAME_ITEXT        3
  149. #define    CLEAR_SCORES_BUTTON        2
  150. #define    OK_APV_DBOX                9
  151. #define    SHOW_INTRO_SCREEN        2
  152. #define    HELP_BUTTON                3
  153. #define    HEAD_ICON                5
  154. #define    OUCH_ICON                7
  155.  
  156. /* icons */
  157. #define    MY_HEAD                    476
  158. #define    OUCH_HEAD                477
  159.  
  160. /* Error Strings */
  161. #define    NO_MBAR                    BASE_RES_ID
  162. #define    NO_MENU                    BASE_RES_ID + 1
  163. #define    NO_WIND                    BASE_RES_ID + 3
  164. #define NO_STR                    BASE_RES_ID + 4
  165. #define CANT_LOAD_SND            BASE_RES_ID + 5
  166. #define    MINUTES_ERROR            BASE_RES_ID + 6
  167. #define    SECONDS_ERROR            BASE_RES_ID + 7
  168. #define    ESCAPED_ERROR            BASE_RES_ID + 8
  169. #define    NO_RGN                    BASE_RES_ID + 9
  170.  
  171. /* 'STR ' resource IDs */
  172. #define    TIMED_OR_ESCAPED        200
  173. #define ANIMAL_SPEED            201
  174. #define    WINDOW_SIZE                202
  175. #define    INCREASE_SPEED            203
  176. #define    SCORE_WHEN_HIT            204
  177. #define    MINUTES_STRING            212
  178. #define    SECONDS_STRING            213
  179. #define    MAX_ESCAPED_STRING        214
  180. #define    HIGH_SCORE_STRING        128
  181. #define    HIGH_NAMES_STRING        131
  182.  
  183. /* cursor */
  184. #define    CROSSHAIR                BASE_RES_ID
  185.  
  186. /* button types */
  187. #define    PLAY_AGAIN_BUTTON        128
  188. #define    QUIT_BUTTON                129
  189.  
  190. /* sounds */
  191. #define    TARZAN_SOUND            409
  192. #define    INTRO_SOUND                410
  193. #define    OUCH_SOUND                411
  194.  
  195. /* PICTs */
  196. #define ANIMAL_PICTURE            BASE_RES_ID  /* picture containing animal bitmaps */
  197.  
  198. /* animals */
  199. #define    RHINO                    0
  200. #define    ELEPHANT                1
  201. #define    ZEBRA                    2
  202. #define    GORILLA                    3
  203. #define    ANTELOPE                4
  204. #define    GIRAFFE                    5
  205. #define    LION                    6
  206. #define    CHEETAH                    7
  207. #define WARTHOG                    8
  208.  
  209. #define    DRAG_THRESHOLD            30
  210.  
  211. #define    WINDOW_HOME_LEFT        5
  212. #define    WINDOW_HOME_TOP            45
  213. #define    NEW_WINDOW_OFFSET        20
  214.  
  215. #define    HOPELESSLY_FATAL_ERROR    "\pGoodness knows what happened!"
  216.  
  217. /* this structure is used for each row.  There is one animal per row. */
  218. struct
  219. {
  220.     Rect    rect;        /* the rect into which the animal bitmap is drawn */
  221.     Boolean    running;    /* is an animal running in the row? */
  222.     int        animal;        /* what type of animal is it? */
  223.     int        speed;        /* how fast does it go? */
  224.     int        step;        /* alternates each pass so that different animal positions are
  225.                             drawn, creating the illusion of a stride */
  226. }
  227. row[20];                /* there can be no more than 20 rows of animals */
  228.  
  229. struct
  230. {
  231.     Rect    rect[2];    /* source rectangles from which animal bitmaps are taken */
  232.     int        value;        /* point value of the animal */
  233.     int        speed;
  234.     int        region[2];    /* array containing two regions for each animal; */
  235.                         /* used to check if someone has clicked inside animal outline */
  236. }
  237. animal[9];                /* there are nine different animals */
  238.  
  239. /* unusual variable names in comments */
  240.  
  241. /*
  242.     increaseSpeed is true when Game Options dialog has the speed of the game
  243.         increase as the score increases.
  244.     easyShoot allows player to score by clicking in a rect surrounding the animal
  245.         instead of clicking directly within outline of the animal (good for kids).
  246.     loopValue keeps track of a group of statements which mimic a for loop, but which
  247.         increment only once every pass through the animation procedure.  This is done
  248.         instead of a for loop so the game can respond to an event after each animal
  249.         is drawn.  
  250.     speedFactor and speedIncrease regulate initial speed of game and increase
  251.         in speed as game play continues
  252. */
  253.  
  254. Boolean            gDone, gamePaused, gameOver, increaseSpeed, easyShoot;
  255. Boolean            standardWindow, showHighScores, escapedGame;
  256. MenuHandle        gAppleMenu, gFileMenu, gEditMenu;
  257. Rect            gDragRect, whereAnimalsRun; /* latter is where animation occurs */
  258. int                windowHeight, windowWidth, lastTicks;
  259.  
  260. int                gameScore, animalsEscaped, animalRows;
  261. int                loopValue, speedFactor, speedIncrease;
  262. long            maxEscaped, timeRemaining, topScores[3];
  263. unsigned long    lastTime;
  264.  
  265. WindowPtr        gameWindow;
  266. GrafPtr            offscreen;
  267. ControlHandle    playAgainControl, quitControl;
  268. Str255            preferenceString[8], name;
  269.  
  270. pascal Boolean GameOptionsDProc(DialogPtr theDialog, EventRecord *theEvent, int *itemHit);
  271.  
  272. main(void)
  273. {
  274.     ToolBoxInit();
  275.     
  276.     SetUpFirstGlobals();
  277.     
  278.     MenuBarInit();
  279.     WindowInit();
  280.     SetUpDragRect();
  281.     
  282.     InitOffscreen();
  283.     SetUpGame();
  284.     IntroDialog();
  285.  
  286.     EventLoop();
  287. }
  288.  
  289. ToolBoxInit(void)
  290. {
  291.     InitGraf(&qd.thePort);
  292.     InitFonts();
  293.     InitWindows();
  294.     InitMenus();
  295.     TEInit();
  296.     InitDialogs(NULL);
  297.     InitCursor();
  298.     MaxApplZone();
  299.     MoreMasters();
  300.     MoreMasters();
  301.     MoreMasters();
  302.     MoreMasters();
  303.     FlushEvents(everyEvent, REMOVE_ALL_EVENTS);
  304. }
  305.  
  306. SetUpFirstGlobals(void)
  307. {    
  308.     DialogPtr    theDialog;
  309.  
  310.     showHighScores = TRUE;
  311. /*
  312.     DialogInit() requires that the Dialog be created since it calls the DITL,
  313.     so we create the dialog, call the procedure, and dispose of the dialog
  314.     without ever displaying the dialog
  315. */
  316.     if ((theDialog = GetNewDialog(GAME_OPTIONS_DIALOG, NULL, M_T_F)) == NULL)
  317.     {
  318.         ErrorHandler(NO_WIND);
  319.     }
  320.     lastTicks = TickCount();
  321.     DialogInit(theDialog);
  322.     DisposDialog(theDialog);
  323. }
  324.  
  325. MenuBarInit(void)
  326. {
  327.     Handle    myMenuBar;
  328.     
  329.     if ((myMenuBar = GetNewMBar(BASE_RES_ID)) == NULL) 
  330.     {
  331.         ErrorHandler(NO_MBAR);
  332.     }
  333.     SetMenuBar(myMenuBar);
  334.     
  335.     if ((gAppleMenu = GetMHandle(APPLE_MENU_ID)) == NULL)
  336.     {
  337.         ErrorHandler(NO_MENU);
  338.     }
  339.     AddResMenu(gAppleMenu, 'DRVR');
  340.     
  341.     if ((gEditMenu = GetMHandle(EDIT_MENU_ID)) == NULL)
  342.     {
  343.         ErrorHandler(NO_MENU);
  344.     }
  345.     
  346.     if ((gFileMenu = GetMHandle(FILE_MENU_ID)) == NULL)
  347.     {
  348.         ErrorHandler(NO_MENU);
  349.     }
  350.     
  351.     DrawMenuBar();
  352. }
  353.  
  354.  
  355. WindowInit(void)
  356. {
  357.     if ((gameWindow = GetNewWindow(BASE_RES_ID, NULL, M_T_F)) == NULL)
  358.     {
  359.         ErrorHandler(NO_WIND);
  360.     }
  361.     playAgainControl = GetNewControl(PLAY_AGAIN_BUTTON, gameWindow);
  362.     quitControl = GetNewControl(QUIT_BUTTON, gameWindow);
  363. }
  364.  
  365. CenterWindow(WindowPtr theWindow)
  366. {
  367.     int        newLeft, newTop;
  368.     Rect    windowRect = theWindow->portRect;
  369.     Rect    screenRect = qd.screenBits.bounds;
  370.     
  371.     newLeft = ((screenRect.right - screenRect.left) - (windowRect.right - windowRect.left)) / 2;
  372.     newTop = ((screenRect.bottom - (screenRect.top + GetMBarHeight() + TITLE_BAR_HEIGHT)) 
  373.         - (windowRect.bottom - windowRect.top)) / 2;
  374.     MoveWindow(theWindow, newLeft, newTop + GetMBarHeight() + TITLE_BAR_HEIGHT, TRUE);
  375.     ShowWindow(theWindow);
  376. }
  377.  
  378. AdjustWindowSize(void)
  379. {
  380.     Rect    windowRect = gameWindow->portRect;
  381.     int        h, v;
  382.     
  383.     SetPort(gameWindow);
  384.     
  385.     if (!standardWindow) /* if it's not the 9" screen window, then */
  386.     {
  387.         SizeWindow(gameWindow,
  388.             qd.screenBits.bounds.right - BORDER, 
  389.             qd.screenBits.bounds.bottom - (GetMBarHeight() + BORDER + TITLE_BAR_HEIGHT),
  390.             TRUE);
  391.     }
  392.     else
  393.     {
  394.         SizeWindow(gameWindow, 506, 298, TRUE);
  395.     }
  396.     
  397.     windowRect = gameWindow->portRect;
  398.     
  399.     windowWidth = windowRect.right - windowRect.left;
  400.     windowHeight = windowRect.bottom - windowRect.top;
  401.     
  402.     CenterWindow(gameWindow);
  403.     TextFont(systemFont);
  404.     
  405.     v = windowHeight / 2 + 20;
  406.     h = windowWidth / 2 - 100;
  407.     MoveControl(playAgainControl, h, v);
  408.     h = windowWidth / 2 + 20;
  409.     MoveControl(quitControl, h, v);
  410. }
  411.  
  412. Boolean CreateOffscreenBitMap(GrafPtr *newOffscreen, Rect *inBounds)
  413. {
  414.     GrafPtr savePort;
  415.     GrafPtr newPort;
  416.  
  417.     GetPort(&savePort);    /* need this to restore thePort after OpenPort */
  418.  
  419.     newPort = (GrafPtr) NewPtr(sizeof(GrafPort));    /* allocate the grafPort */
  420.     if (MemError() != noErr)
  421.     {
  422.         return false;                 /* failed to allocate the off-screen port */
  423.     }
  424. /*
  425.     the call to OpenPort does the following . . . 
  426.         allocates space for visRgn (set to screenBits.bounds) and clipRgn (set wide open)
  427.         sets portBits to screenBits
  428.         sets portRect to screenBits.bounds
  429.         etc. (see IM I-163,164)
  430.         side effect: does a SetPort(&offScreen)
  431. */
  432.     OpenPort(newPort);
  433.     /* make bitmap the size of the bounds that caller supplied */
  434.     newPort->portRect = *inBounds;
  435.     newPort->portBits.bounds = *inBounds;
  436.     RectRgn(newPort->clipRgn, inBounds);    /* avoid wide-open clipRgn, to be safe  */
  437.     RectRgn(newPort->visRgn, inBounds);     /* in case newBounds is > screen bounds */
  438.  
  439.     /* rowBytes is size of row, it must be rounded up to an even number of bytes */
  440.     newPort->portBits.rowBytes = ((inBounds->right - inBounds->left + 15) >> 4) << 1;
  441.  
  442.     /* number of bytes in BitMap is rowBytes * number of rows */
  443.     /* see notes at end of Technical Note about using _NewHandle rather than _NewPtr */
  444.     newPort->portBits.baseAddr =
  445.         NewPtr(newPort->portBits.rowBytes * (long) (inBounds->bottom - inBounds->top));
  446.     if (MemError() != noErr)
  447.     {   /* check to see if we had enough room for the bits */
  448.         SetPort(savePort);
  449.         ClosePort(newPort);      /* dump the visRgn and clipRgn */
  450.         DisposPtr((Ptr)newPort); /* dump the GrafPort */
  451.         return false;            /* tell caller we failed */
  452.     }
  453.     /* since the bits are just memory, let's clear them before we start */
  454.     EraseRect(inBounds);     /* OpenPort did a SetPort(newPort) so we are ok */
  455.     *newOffscreen = newPort;
  456.     SetPort(savePort);
  457.     return true;               /* tell caller we succeeded! */
  458. }
  459.  
  460. void DestroyOffscreenBitMap(GrafPtr oldOffscreen)
  461. {
  462.     ClosePort(oldOffscreen);                        /* dump the visRgn and clipRgn */
  463.     DisposPtr(oldOffscreen->portBits.baseAddr);        /* dump the bits */
  464.     DisposPtr((Ptr)oldOffscreen);                    /* dump the port */
  465. }
  466.  
  467. InitOffscreen(void)
  468. {
  469.     Rect    offScreenRect;
  470.     
  471.     SetRect(&offScreenRect, 0, 0, 227, 151);         /* size of ANIMAL_PICTURE rect */
  472.  
  473.     if (!CreateOffscreenBitMap(&offscreen, &offScreenRect)) 
  474.     {
  475.         SysBeep(1);
  476.         ExitToShell();
  477.     }
  478.     
  479.     SetPort(offscreen);
  480.     DrawPicture(GetPicture(ANIMAL_PICTURE), &offScreenRect);
  481.     SetPort(gameWindow);
  482. }
  483.  
  484. SetUpDragRect(void)
  485. {
  486.     gDragRect = qd.screenBits.bounds;
  487.     gDragRect.left += DRAG_THRESHOLD;
  488.     gDragRect.right -= DRAG_THRESHOLD;
  489.     gDragRect.bottom -= DRAG_THRESHOLD;
  490. }
  491.  
  492. DoSound(int whichOne, Boolean asynch)
  493. {
  494.     Handle                    theSnd;
  495.     static SndChannelPtr    chanPtr;
  496.     OSErr                    err;
  497.  
  498.     theSnd = GetResource('snd ', whichOne);
  499.     MoveHHi((Handle) theSnd);
  500.     HLock((Handle) theSnd);
  501.     if (theSnd != NULL) 
  502.     {
  503.         if (chanPtr != NULL)
  504.         {
  505.             (void) SndDisposeChannel(chanPtr, TRUE);
  506.             chanPtr = NULL;
  507.         }
  508.         
  509.         chanPtr = NULL;
  510.         
  511.         err = SndNewChannel(&chanPtr, 0, 0, NULL);
  512.         
  513.         if ((asynch) && (err == noErr))
  514.         {
  515.             (void) SndPlay(chanPtr, (SndListHandle)theSnd, TRUE);
  516.         }
  517.         else
  518.         {
  519.             (void) SndPlay(NULL, (SndListHandle)theSnd, FALSE);
  520.         }
  521.     }
  522.     HUnlock((Handle) theSnd);
  523. }
  524.  
  525. SetUpGame(void)
  526. {
  527.     register int    i;
  528.     long            stringValue;
  529.     Rect            windowRect;
  530.     
  531.     SetPreferences();                                 /* get current game settings */
  532.     if (showHighScores)
  533.     {
  534.         GetHighScores();
  535.     }
  536.     AdjustWindowSize();
  537.     HideControl(playAgainControl);
  538.     HideControl(quitControl);
  539.  
  540.     SetRect(&windowRect, 0, 0, windowWidth, windowHeight);
  541.     EraseRect(&windowRect);
  542.     speedIncrease = 0;
  543.     
  544.     /* Set Animal Values */
  545.     
  546.     SetRect(&animal[RHINO].rect[0], 2, 2, 35, 35);
  547.     SetRect(&animal[RHINO].rect[1], 40, 2, 73, 35);
  548.     animal[RHINO].value = 10;
  549.     animal[RHINO].speed = 2;
  550.     animal[RHINO].region[0] = 400;
  551.     animal[RHINO].region[1] = 401;
  552.                 
  553.     SetRect(&animal[ELEPHANT].rect[0], 2, 40, 35, 73);
  554.     SetRect(&animal[ELEPHANT].rect[1], 40, 40, 73, 73);
  555.     animal[ELEPHANT].value = 10;
  556.     animal[ELEPHANT].speed = 2;
  557.     animal[ELEPHANT].region[0] = 402;
  558.     animal[ELEPHANT].region[1] = 403;
  559.                 
  560.     SetRect(&animal[ZEBRA].rect[0], 2, 78, 35, 111);
  561.     SetRect(&animal[ZEBRA].rect[1], 40, 78, 73, 111);
  562.     animal[ZEBRA].value = 60;
  563.     animal[ZEBRA].speed = 4;
  564.     animal[ZEBRA].region[0] = 404;
  565.     animal[ZEBRA].region[1] = 405;
  566.         
  567.     SetRect(&animal[GORILLA].rect[0], 2, 116, 35, 149);
  568.     SetRect(&animal[GORILLA].rect[1], 40, 116, 73, 149);
  569.     animal[GORILLA].value = 50;
  570.     animal[GORILLA].speed = 3;
  571.     animal[GORILLA].region[0] = 406;
  572.     animal[GORILLA].region[1] = 407;
  573.             
  574.     SetRect(&animal[ANTELOPE].rect[0], 78, 2, 111, 35);
  575.     SetRect(&animal[ANTELOPE].rect[1], 116, 2, 149, 35);
  576.     animal[ANTELOPE].value = 75;
  577.     animal[ANTELOPE].speed = 5;
  578.     animal[ANTELOPE].region[0] = 408;
  579.     animal[ANTELOPE].region[1] = 409;
  580.         
  581.     SetRect(&animal[GIRAFFE].rect[0], 78, 40, 111, 73);
  582.     SetRect(&animal[GIRAFFE].rect[1], 116, 40, 149, 73);
  583.     animal[GIRAFFE].value = 60;
  584.     animal[GIRAFFE].speed = 4;
  585.     animal[GIRAFFE].region[0] = 410;
  586.     animal[GIRAFFE].region[1] = 411;
  587.                 
  588.     SetRect(&animal[LION].rect[0], 78, 78, 111, 111);
  589.     SetRect(&animal[LION].rect[1], 116, 78, 149, 111);
  590.     animal[LION].value = 75;
  591.     animal[LION].speed = 5;
  592.     animal[LION].region[0] = 412;
  593.     animal[LION].region[1] = 413;
  594.             
  595.     SetRect(&animal[CHEETAH].rect[0], 78, 116, 111, 149);
  596.     SetRect(&animal[CHEETAH].rect[1], 116, 116, 149, 149);
  597.     animal[CHEETAH].value = 80;
  598.     animal[CHEETAH].speed = 6;
  599.     animal[CHEETAH].region[0] = 414;
  600.     animal[CHEETAH].region[1] = 415;
  601.                 
  602.     SetRect(&animal[WARTHOG].rect[0], 154, 2, 187, 35);
  603.     SetRect(&animal[WARTHOG].rect[1], 192, 2, 225, 35);
  604.     animal[WARTHOG].value = 60;
  605.     animal[WARTHOG].speed = 4;
  606.     animal[WARTHOG].region[0] = 416;
  607.     animal[WARTHOG].region[1] = 417;
  608.             
  609.     gameScore = 0;
  610.     
  611.     if (escapedGame)
  612.     {
  613.         animalsEscaped = 0;
  614.     }
  615.     else
  616.     {
  617.         StringToNum(preferenceString[MINUTES], &stringValue);
  618.         timeRemaining = stringValue * 60;
  619.         StringToNum(preferenceString[SECONDS], &stringValue);
  620.         timeRemaining += stringValue;
  621.         GetDateTime(&lastTime);
  622.     }
  623.     
  624.     DrawScoreBar();
  625.     
  626.     SetRect(&whereAnimalsRun, 0, 20, windowWidth, windowHeight);
  627.         
  628.     animalRows = (windowHeight - 20) / 33;
  629.     
  630.     if (animalRows > 20)
  631.     {
  632.         animalRows = 20;
  633.     }
  634.             
  635.     for (i = 0; i < animalRows; i++)
  636.     {
  637.         SetRect(&row[i].rect, 0, 33 * i + 20, 33, 33 * i + 53);
  638.         row[i].running = FALSE;
  639.     }
  640.     loopValue = 0;
  641.     gamePaused = FALSE;
  642.     gameOver = FALSE;
  643.     
  644. }
  645.  
  646.  
  647. SetPreferences(void)
  648. {
  649.     register int    i;
  650.     long            currentSetting;
  651.     
  652.     for (i = 0; i <= 4; i++)
  653.     {
  654.         StringToNum(preferenceString[i], ¤tSetting);
  655.         switch (currentSetting)
  656.         {
  657.             case TIMED_RADIO:
  658.             case ESCAPED_RADIO:
  659.                 escapedGame = (currentSetting == ESCAPED_RADIO);
  660.                 break;
  661.             case NINE_INCH_RADIO:
  662.             case CURRENT_SCREEN_RADIO:
  663.                 standardWindow = (currentSetting == NINE_INCH_RADIO);
  664.                 break;
  665.             case INCREASE_YES_RADIO:
  666.             case INCREASE_NO_RADIO:
  667.                 increaseSpeed = (currentSetting == INCREASE_YES_RADIO);
  668.                 break;
  669.             case SLOW_RADIO:
  670.                 speedFactor = 1;
  671.                 break;
  672.             case MEDIUM_RADIO:
  673.                 speedFactor = 3;
  674.                 break;
  675.             case FAST_RADIO:
  676.                 speedFactor = 5;
  677.                 break;
  678.             case IN_ANIMAL_OUTLINE_RADIO:
  679.             case IN_BOX_SURROUNDING_ANIMAL_RADIO:
  680.                 easyShoot = (currentSetting == IN_BOX_SURROUNDING_ANIMAL_RADIO);
  681.                 break;
  682.             default:
  683.                 break;
  684.         }
  685.     }
  686.     StringToNum(preferenceString[MAX_ESCAPED], &maxEscaped);
  687. }
  688.  
  689. GetHighScores(void)
  690. {
  691.     register int    i;
  692.     StringHandle    theString;
  693.                 
  694.     for (i = 0; i <= 2; i++)
  695.     {
  696.         if ((theString = GetString(HIGH_SCORE_STRING + i)) == NULL)
  697.             ErrorHandler(NO_STR);
  698.         MoveHHi((Handle) theString);
  699.         HLock((Handle) theString);    
  700.         StringToNum(*theString, &topScores[i]);
  701.         HUnlock((Handle) theString);
  702.     }
  703. }
  704.  
  705. DrawScoreBar(void)
  706. {
  707.     Str255    scoreString;
  708.     int        length;
  709.     Rect    theRect;
  710.     
  711.     SetRect(&theRect, 0, 0, windowWidth, 20);
  712.     EraseRect(&theRect);
  713.     
  714.     MoveTo(2, 17);
  715.     DrawString("\pScore: ");
  716.     NumToString(gameScore, scoreString);
  717.     DrawString(scoreString);
  718.  
  719.     if (showHighScores)
  720.     {
  721.         PostHighScore();
  722.     }
  723.     
  724.     if (escapedGame)
  725.     {
  726.         length = StringWidth("\pAnimals Escaped: 500") + 2;
  727.         MoveTo(windowWidth - length, 17);
  728.         NumToString(animalsEscaped, scoreString);
  729.         DrawString("\pAnimals Escaped: ");
  730.         DrawString(scoreString);
  731.     }
  732.     else
  733.     {
  734.         length = StringWidth("\pTime Remaining: 00:00") + 2;
  735.         MoveTo(windowWidth - length, 17);
  736.         DrawString("\pTime Remaining: ");
  737.         PostTimeRemaining();
  738.     }
  739. }
  740.  
  741. PostTimeRemaining(void)
  742. {
  743.     long    diffTime;
  744.     unsigned long currentTime;
  745.     int        mins, secs, length;
  746.     Str255    timeString;
  747.     Rect    timeRect;
  748.     
  749.     GetDateTime(¤tTime);
  750.     diffTime = currentTime - lastTime;
  751.     if (diffTime > 0)
  752.     {
  753.         length = StringWidth("\p00:00") + 2;
  754.         SetRect(&timeRect, windowWidth - length, 0, windowWidth, 17);
  755.         EraseRect(&timeRect);
  756.         MoveTo(windowWidth - length, 17);
  757.         timeRemaining -= diffTime;
  758.         if (timeRemaining > 0)
  759.         {
  760.             mins = timeRemaining / 60;
  761.             NumToString(mins, timeString);
  762.             DrawString(timeString);
  763.             DrawString("\p:");
  764.             secs = timeRemaining - mins * 60;
  765.             if (secs < 10)
  766.             {
  767.                 DrawString("\p0");
  768.             }
  769.             NumToString(secs, timeString);
  770.             DrawString(timeString);
  771.         }
  772.         else
  773.         {
  774.             DrawString("\p0:00");
  775.             EndGame();
  776.         }
  777.     }
  778.     GetDateTime(&lastTime);
  779. }
  780.  
  781. PostHighScore(void)
  782. {
  783.     StringHandle    theString;
  784.     int                length;
  785.     
  786.     if ((theString = GetString(HIGH_SCORE_STRING)) == NULL)
  787.     {
  788.         ErrorHandler(NO_STR);
  789.     }
  790.     MoveHHi((Handle) theString);
  791.     HLock((Handle) theString);
  792.     
  793.     length = StringWidth("\pHigh Score: ") + 2 + StringWidth(*theString);
  794.     MoveTo((windowWidth - length) / 2, 17);
  795.     DrawString("\pHigh Score: ");
  796.     DrawString(*theString);
  797.     
  798.     HUnlock((Handle) theString);
  799. }
  800.  
  801. EventLoop(void)
  802. {
  803.     Boolean        hasGNE = WNEAvailable();
  804.     RgnHandle    cursorRgn = NewRgn();
  805.     Boolean        gotEvent;
  806.     EventRecord    event;
  807.     
  808.     gDone = FALSE;
  809.     
  810.     while (!gDone)
  811.     {
  812.         if (hasGNE)
  813.         {
  814.             gotEvent = WaitNextEvent(everyEvent, &event, (long)NULL, cursorRgn);
  815.         }
  816.         else
  817.         {
  818.             SystemTask();
  819.             gotEvent = GetNextEvent(everyEvent, &event);
  820.         }
  821.         
  822.         AdjustCursor(event.where);
  823.         
  824.         if (gotEvent)
  825.         {
  826.             DoEvent(event);
  827.         }
  828.         else
  829.         {
  830.             DoIdle();
  831.         }
  832.     }
  833. }
  834.  
  835. AdjustCursor(Point where)
  836. {    
  837.     if (FrontWindow() != gameWindow)
  838.     {
  839.         SetCursor(&qd.arrow);
  840.     }
  841.     else
  842.     {
  843.         GlobalToLocal(&where);
  844.         if (PtInRect(where, &whereAnimalsRun))
  845.         {
  846.             SetCursor(*GetCursor(CROSSHAIR));
  847.         }
  848.         else
  849.         {
  850.             SetCursor(&qd.arrow);
  851.         }
  852.     }
  853. }
  854.  
  855. DoEvent(EventRecord event)
  856. {
  857.     GrafPtr        oldPort;
  858.  
  859.     switch (event.what)
  860.     {
  861.         case mouseDown:
  862.             DoMouseDown(event);
  863.             break;
  864.         case keyDown:
  865.         case autoKey:
  866.             if ((event.modifiers & cmdKey) != 0)
  867.             {
  868.                 AdjustMenus();
  869.                 DoMenuChoice(MenuKey(event.message & charCodeMask));
  870.             }
  871.             break;
  872.         case updateEvt:
  873.             if (!IsDAWindow((WindowPtr) event.message))
  874.             {
  875.                 GetPort(&oldPort);
  876.                 SetPort((GrafPtr) event.message);
  877.                 BeginUpdate((GrafPtr) event.message);
  878.                 GetDateTime(&lastTime);
  879.                 if (FrontWindow() == gameWindow)
  880.                 {
  881.                     DrawScoreBar();
  882.                     if ((gameOver) || (gamePaused))
  883.                     {
  884.                         DrawContent();
  885.                     }
  886.                     if (gameOver)
  887.                     {
  888.                         WriteGameOver();
  889.                     }
  890.                     DrawControls(gameWindow);
  891.                 }
  892.                 EndUpdate((GrafPtr) event.message);
  893.                 SetPort(oldPort);
  894.             }
  895.             break;
  896.         default:
  897.             break;
  898.     }
  899. }
  900.  
  901. DoIdle(void)
  902. {
  903.     if ((!gamePaused) && (!gameOver))
  904.     {
  905.         if ((TickCount() - lastTicks) >= TICK_DELAY)
  906.         {
  907.             Animate();
  908.             lastTicks = TickCount();
  909.         }
  910.     }
  911. }
  912.  
  913. DoMouseDown(EventRecord event)
  914. {
  915.     WindowPtr    whichWindow;
  916.     
  917.     switch (FindWindow(event.where, &whichWindow))
  918.     {
  919.         case inMenuBar:
  920.             AdjustMenus();
  921.             DoMenuChoice(MenuSelect(event.where));
  922.             break;
  923.         case inSysWindow:
  924.             SystemClick(&event, whichWindow);
  925.             break;
  926.         case inDrag:
  927.             DragWindow(whichWindow, event.where, &gDragRect);
  928.             break;
  929.         case inContent:
  930.             SelectWindow(whichWindow);
  931.             if ((!gamePaused) && (!gameOver))
  932.             {
  933.                 HandleInContent(event.where);
  934.             }
  935.             if (gameOver)
  936.             {
  937.                 DoGameOverButtons(event.where);
  938.             }
  939.             break;
  940.         default:
  941.             break;
  942.     }
  943. }
  944.  
  945. AdjustMenus(void)
  946. {
  947.     if (IsDAWindow(FrontWindow()))
  948.     {
  949.         EnableItem(gEditMenu, UNDO_ITEM);
  950.         EnableItem(gEditMenu, CUT_ITEM);
  951.         EnableItem(gEditMenu, PASTE_ITEM);
  952.         EnableItem(gEditMenu, COPY_ITEM);
  953.         EnableItem(gEditMenu, CLEAR_ITEM);
  954.     }
  955.     else
  956.     {
  957.         DisableItem(gEditMenu, UNDO_ITEM);
  958.         DisableItem(gEditMenu, CUT_ITEM);
  959.         DisableItem(gEditMenu, PASTE_ITEM);
  960.         DisableItem(gEditMenu, COPY_ITEM);
  961.         DisableItem(gEditMenu, CLEAR_ITEM);
  962.     }
  963.     
  964.     if (gameOver)
  965.     {
  966.         DisableItem(gFileMenu, PAUSE_RESUME_ITEM);
  967.         DisableItem(gFileMenu, STOP_ITEM);
  968.     }
  969.     else
  970.     {
  971.         EnableItem(gFileMenu, PAUSE_RESUME_ITEM);
  972.         EnableItem(gFileMenu, STOP_ITEM);        
  973.     }
  974.     
  975.     if (gamePaused)
  976.     {
  977.         SetItem(gFileMenu, PAUSE_RESUME_ITEM, "\pResume");
  978.     }
  979.     else
  980.     {
  981.         SetItem(gFileMenu, PAUSE_RESUME_ITEM, "\pPause");
  982.     }        
  983. }
  984.  
  985. IsDAWindow(WindowPtr whichWindow)
  986. {
  987.     if (whichWindow == NULL)
  988.     {
  989.         return (FALSE);
  990.     }
  991.     else
  992.     {
  993.         return (((WindowPeek) whichWindow)->windowKind < 0);
  994.     }
  995. }
  996.  
  997. DoMenuChoice(long selection)
  998. {
  999.     int    menu;
  1000.     int    item;
  1001.     
  1002.     if (selection != 0)
  1003.     {
  1004.         menu = HiWord(selection);
  1005.         item = LoWord(selection);
  1006.         switch (menu)
  1007.         {
  1008.             case APPLE_MENU_ID:
  1009.                 DoAppleChoice(item);
  1010.                 break;
  1011.             case FILE_MENU_ID:
  1012.                 DoFileChoice(item);
  1013.             case EDIT_MENU_ID:
  1014.                 DoEditChoice(item);
  1015.                 break;
  1016.             case GAME_MENU_ID:
  1017.                 DoGameChoice(item);
  1018.                 break;
  1019.             default:
  1020.                 break;
  1021.         }
  1022.         HiliteMenu(0);
  1023.     }
  1024. }
  1025.  
  1026. DoAppleChoice(int item)
  1027. {
  1028.     Str255    accName;
  1029.     GrafPtr    oldPort;
  1030.     
  1031.     switch (item)
  1032.     {
  1033.         case ABOUT_ITEM:
  1034.             AboutDialog();
  1035.             break;
  1036.         default:
  1037.             GetItem(gAppleMenu, item, accName);
  1038.             GetPort(&oldPort);
  1039.             (void) OpenDeskAcc(accName);
  1040.             SetPort(oldPort);
  1041.             break;
  1042.     }
  1043. }
  1044.  
  1045. DoFileChoice(int item)
  1046. {
  1047.     switch (item)
  1048.     {
  1049.         case NEW_GAME_ITEM:
  1050.             SetUpGame();
  1051.             break;
  1052.         case PAUSE_RESUME_ITEM:
  1053.             if (!gamePaused)
  1054.             {
  1055.                 gamePaused = TRUE;
  1056.             }
  1057.             else
  1058.             {
  1059.                 gamePaused = FALSE;        
  1060.                 GetDateTime(&lastTime);
  1061.             }        
  1062.             break;
  1063.         case STOP_ITEM:
  1064.             EndGame();
  1065.             break;
  1066.         case QUIT_ITEM:
  1067.             gDone = TRUE;
  1068.             break;
  1069.         default:
  1070.             break;
  1071.     }
  1072. }
  1073.  
  1074. DoEditChoice(int item)
  1075. {
  1076.     SystemEdit(item - 1);
  1077. }
  1078.  
  1079. DoGameChoice(int item)
  1080. {
  1081.     switch (item)
  1082.     {
  1083.         case GAME_OPTIONS_ITEM:
  1084.             GameOptionsDialog();
  1085.             break;
  1086.         case ANIMAL_POINT_VALUES_ITEM:
  1087.             AnimalPointValuesDialog();
  1088.             break;
  1089.         case HALL_OF_FAME_ITEM:
  1090.             HallOfFameDialog();
  1091.             break;
  1092.         default:
  1093.             break;
  1094.     }
  1095. }
  1096.  
  1097. HandleInContent(Point where)
  1098. {
  1099.     register int    i;
  1100.     int                h, v;
  1101.     RgnHandle        animalRgn;
  1102.     
  1103.     GlobalToLocal(&where);
  1104.     
  1105.     for (i = 0; i < animalRows; i++)
  1106.     {
  1107.         if (PtInRect(where, &row[i].rect))
  1108.         {
  1109.             if (!easyShoot)
  1110.             {
  1111.                 animalRgn = (RgnHandle) GetResource('RGN ', animal[row[i].animal].region[row[i].step]);
  1112.                 
  1113.                 h = row[i].rect.right - (**animalRgn).rgnBBox.right;
  1114.                 v = row[i].rect.bottom - (**animalRgn).rgnBBox.bottom;
  1115.             
  1116.                 OffsetRgn(animalRgn, h, v);
  1117.                 
  1118.                 if (PtInRgn(where, animalRgn)) 
  1119.                 {
  1120.                     PaintRgn(animalRgn);
  1121.                     DoSound(BASE_RES_ID + row[i].animal, TRUE);
  1122.                     AnimalShot(i);
  1123.                 }
  1124.             }    
  1125.             else
  1126.             {
  1127.                 DoSound(BASE_RES_ID + row[i].animal, TRUE);
  1128.                 AnimalShot(i);
  1129.             }    
  1130.         }
  1131.     }
  1132. }
  1133.  
  1134. DoGameOverButtons(Point where)
  1135. {
  1136.     ControlHandle    whichControl;
  1137.     
  1138.     GlobalToLocal(&where);
  1139.     
  1140.     (void) FindControl(where, gameWindow, &whichControl);
  1141.     
  1142.     if (whichControl != NULL)
  1143.     {
  1144.         if (TrackControl(whichControl, where, NULL) != 0)
  1145.         {
  1146.             if (whichControl == playAgainControl)
  1147.             {
  1148.                 SetUpGame();
  1149.             }
  1150.             if (whichControl == quitControl)
  1151.             {
  1152.                 ExitToShell();
  1153.             }
  1154.         }
  1155.     }
  1156. }
  1157.  
  1158. AnimalShot(int i)
  1159. {
  1160.     Str255    scoreString;
  1161.     int        length;
  1162.     Rect    scoreRect;
  1163.     
  1164.     gameScore += animal[row[i].animal].value;
  1165.     length = StringWidth("\pScore: ") + 2;
  1166.     SetRect(&scoreRect, length, 0, length + StringWidth("\p000000"), 20);
  1167.     EraseRect(&scoreRect);
  1168.     MoveTo(length, 17);
  1169.     NumToString(gameScore, scoreString);
  1170.     DrawString(scoreString);
  1171.         
  1172.     EraseRect(&row[i].rect);
  1173.     row[i].rect.left = 0;
  1174.     row[i].rect.right = 33;
  1175.        row[i].running = FALSE;
  1176.        
  1177.        if (increaseSpeed)
  1178.        {
  1179.         speedIncrease = gameScore / 1000;
  1180.     }
  1181. }
  1182.  
  1183. ErrorHandler(int stringNum)
  1184. {
  1185.     StringHandle    errorStringH;
  1186.     
  1187.     if ((errorStringH = GetString(stringNum)) == NULL)
  1188.     {
  1189.         ParamText(HOPELESSLY_FATAL_ERROR, NULL, NULL, NULL);
  1190.     }
  1191.     else
  1192.     {
  1193.         MoveHHi((Handle) errorStringH);
  1194.         HLock((Handle) errorStringH);
  1195.         ParamText(*errorStringH, NULL, NULL, NULL);
  1196.         HUnlock((Handle) errorStringH);
  1197.     }
  1198.     StopAlert(ERROR_ALERT_ID, NULL);
  1199.     ExitToShell();
  1200. }
  1201.  
  1202. Animate(void)
  1203. {
  1204.     int        r;
  1205.     Rect    copyRect;
  1206.     GrafPtr    secondOffScreen;
  1207.     
  1208.     /* Open loop goes from 0 to animalRows - 1 & allows for WaitNextEvent to occur
  1209.         between each animal drawing */
  1210.     
  1211.     loopValue %= animalRows;
  1212.     
  1213.     if (!row[loopValue].running)
  1214.     {
  1215.         row[loopValue].running = TRUE;
  1216.         r = Randomize(9);
  1217.         row[loopValue].animal = r;
  1218.         row[loopValue].speed = animal[r].speed;
  1219.         row[loopValue].step = 0;
  1220.     }
  1221.     
  1222.     row[loopValue].step = (row[loopValue].step == 1) ? 0 : 1;
  1223.     
  1224.     OffsetRect(&row[loopValue].rect,
  1225.         row[loopValue].speed * speedFactor + speedIncrease, 0);
  1226.  
  1227.     SetRect(©Rect,
  1228.         row[loopValue].rect.left - (row[loopValue].speed * speedFactor + speedIncrease),
  1229.         row[loopValue].rect.top,
  1230.         row[loopValue].rect.right,
  1231.         row[loopValue].rect.bottom);
  1232.  
  1233.     if (!CreateOffscreenBitMap(&secondOffScreen, ©Rect)) 
  1234.     {
  1235.         SysBeep(1);
  1236.         ExitToShell();
  1237.      }
  1238.       SetPort(secondOffScreen);
  1239.        EraseRect(©Rect);
  1240.            
  1241.        CopyBits(&offscreen->portBits, &secondOffScreen->portBits, 
  1242.            &animal[row[loopValue].animal].rect[row[loopValue].step], &row[loopValue].rect, srcCopy, NULL);
  1243.        SetPort(gameWindow);
  1244.        CopyBits(&secondOffScreen->portBits, &gameWindow->portBits,
  1245.            ©Rect, ©Rect, srcCopy, NULL);
  1246.        DestroyOffscreenBitMap(secondOffScreen);
  1247.  
  1248.        if (row[loopValue].rect.left >= windowWidth)
  1249.        {
  1250.         row[loopValue].rect.left = 0;
  1251.         row[loopValue].rect.right = 33;
  1252.            row[loopValue].running = FALSE;
  1253.            if (escapedGame)
  1254.            {
  1255.              AnimalEscaped();
  1256.          }
  1257.        }
  1258.  
  1259.     loopValue++;
  1260.     if (!escapedGame)
  1261.     {
  1262.         PostTimeRemaining();
  1263.     }
  1264. }
  1265.  
  1266. DrawContent(void)
  1267. {
  1268.     GrafPtr            oldPort;
  1269.     register int    i;
  1270.     
  1271.     GetPort(&oldPort);
  1272.     SetPort(gameWindow);
  1273.  
  1274.     for (i = 0; i < animalRows; i++)
  1275.     {
  1276.            CopyBits(&offscreen->portBits, &gameWindow->portBits,
  1277.              &animal[row[i].animal].rect[row[i].step], &row[i].rect,srcCopy, NULL);
  1278.      }
  1279.     SetPort(oldPort);
  1280. }
  1281.  
  1282. Randomize(int range)
  1283. {
  1284.      long    rawResult = Random();
  1285.      
  1286.      if (rawResult < 0)
  1287.      {
  1288.          rawResult *= -1;
  1289.      }
  1290.      return (rawResult % range);
  1291. }
  1292.  
  1293. AnimalEscaped(void)
  1294. {
  1295.     int        length = StringWidth("\p000") + 2;
  1296.     Rect    escapedRect;
  1297.      Str255    scoreString;
  1298.         
  1299.     animalsEscaped++;
  1300.     SetRect(&escapedRect, windowWidth - length, 0, windowWidth, 20);
  1301.     MoveTo(windowWidth - length, 17);
  1302.     NumToString(animalsEscaped, scoreString);
  1303.     EraseRect(&escapedRect);
  1304.     DrawString(scoreString);
  1305.     if ((escapedGame) && (maxEscaped <= animalsEscaped))
  1306.     {
  1307.         EndGame();
  1308.     }
  1309. }
  1310.  
  1311.  
  1312. WriteGameOver(void)
  1313. {
  1314.     int        length = StringWidth("\pGame Over");
  1315.     Rect    myRect;
  1316.     
  1317.     SetRect(&myRect, windowWidth / 2 - length / 2 - 2, windowHeight / 2 - 10, 
  1318.             windowWidth / 2 + length / 2 + 2, windowHeight / 2 + 10);
  1319.     EraseRect(&myRect);
  1320.     MoveTo(windowWidth / 2 - length / 2, windowHeight / 2);
  1321.     DrawString("\pGame Over");
  1322. }
  1323.  
  1324. EndOfGameControls(void)
  1325. {
  1326.     ShowControl(playAgainControl);
  1327.     ShowControl(quitControl);
  1328. }
  1329.  
  1330. EndGame(void)
  1331. {
  1332.     gameOver = TRUE;
  1333.     WriteGameOver();
  1334.     EndOfGameControls();
  1335.     if ((gameScore >= topScores[2]) && (showHighScores))
  1336.     {
  1337.         UpdateHighScores();
  1338.     }
  1339. }
  1340.  
  1341. UpdateHighScores(void)
  1342. {
  1343.     register int    i;
  1344.     StringHandle    theString, topNames[3];
  1345.     Str255            numString;
  1346.     
  1347.     GetPlayerName();
  1348.     
  1349.     for (i = 0; i <= 2; i++)
  1350.     {
  1351.         if ((theString = GetString(HIGH_NAMES_STRING + i)) == NULL)
  1352.         {
  1353.             ErrorHandler(NO_STR);
  1354.         }
  1355.         MoveHHi((Handle) theString);
  1356.         HLock((Handle) theString);    
  1357.         topNames[i] = theString;
  1358.         HUnlock((Handle) theString);    
  1359.     }
  1360.         
  1361.     if (gameScore >= topScores[0])
  1362.     {
  1363.         topScores[2] = topScores[1];
  1364.         SetString(topNames[2], *topNames[1]);
  1365.         topScores[1] = topScores[0];
  1366.         SetString(topNames[1], *topNames[0]);
  1367.         topScores[0] = gameScore;
  1368.         SetString(topNames[0], name);
  1369.     }
  1370.     else if (gameScore >= topScores[1])
  1371.     {
  1372.         topScores[2] = topScores[1];
  1373.         SetString(topNames[2], *topNames[1]);
  1374.         topScores[1] = gameScore;
  1375.         SetString(topNames[1], name);
  1376.     }
  1377.     else
  1378.     {
  1379.         topScores[2] = gameScore;
  1380.         SetString(topNames[2], name);
  1381.     }
  1382.     
  1383.     for (i = 0; i <= 2; i++)
  1384.     {
  1385.         if ((theString = GetString(HIGH_NAMES_STRING + i)) == NULL)
  1386.         {
  1387.             ErrorHandler(NO_STR);
  1388.         }
  1389.         MoveHHi((Handle) theString);
  1390.         HLock((Handle) theString);
  1391.         SetString(theString, *topNames[i]);
  1392.         ChangedResource((Handle) theString);
  1393.         WriteResource((Handle) theString);
  1394.         HUnlock((Handle) theString);
  1395.         
  1396.         if ((theString = GetString(HIGH_SCORE_STRING + i)) == NULL)
  1397.         {
  1398.             ErrorHandler(NO_STR);
  1399.         }
  1400.         NumToString(topScores[i], numString);
  1401.         SetString(theString, numString);
  1402.         ChangedResource((Handle) theString);
  1403.         WriteResource((Handle) theString);
  1404.     }
  1405.     
  1406.     HallOfFameDialog();
  1407. }
  1408.  
  1409. GetPlayerName(void)
  1410. {
  1411.     GrafPtr         savePort;
  1412.     int                stringNum = 502 - (gameScore >= topScores[1]) - (gameScore >= topScores[0]);
  1413.     StringHandle    whichString;
  1414.     DialogPtr        theDialog;
  1415.     short            itemHit;
  1416.     short            itemType;
  1417.     Handle            itemHandle;
  1418.     Rect            itemRect;
  1419.     Boolean            dialogDone = FALSE;
  1420.     
  1421.     GetPort(&savePort);
  1422.  
  1423.     if ((whichString = GetString(stringNum)) == NULL)
  1424.     {
  1425.         ParamText(HOPELESSLY_FATAL_ERROR, NULL, NULL, NULL);
  1426.     }
  1427.     MoveHHi((Handle) whichString);
  1428.     HLock((Handle) whichString);
  1429.     ParamText(*whichString, NULL, NULL, NULL);
  1430.     HUnlock((Handle) whichString);
  1431.     if ((theDialog = GetNewDialog(PLAYER_NAME_DIALOG, NULL, M_T_F)) == NULL)
  1432.     {
  1433.         ErrorHandler(NO_WIND);
  1434.     }
  1435.     SelIText(theDialog, PLAYER_NAME_ITEXT, 0, 255);
  1436.     CenterWindow(theDialog);
  1437.     ShowWindow(theDialog);
  1438.     
  1439.     SetPort(theDialog);
  1440.     
  1441.     SetCursor(&qd.arrow);
  1442.     
  1443.     DoSound(TARZAN_SOUND, TRUE);
  1444.     
  1445.     while (!dialogDone)
  1446.     {
  1447.         ModalDialog(NULL, &itemHit);
  1448.         switch (itemHit)
  1449.         {
  1450.             case OK_BUTTON:
  1451.                 dialogDone = TRUE;
  1452.                 break;
  1453.             default:
  1454.                 break;
  1455.         }
  1456.     }
  1457.     
  1458.     GetDItem(theDialog, PLAYER_NAME_ITEXT, &itemType, &itemHandle, &itemRect);
  1459.     MoveHHi((Handle) itemHandle);
  1460.     HLock(itemHandle);
  1461.     GetIText(itemHandle, name);
  1462.     HUnlock(itemHandle);
  1463.     
  1464.     DisposDialog(theDialog);
  1465.     SetPort(savePort);
  1466. }
  1467.  
  1468. AnimalPointValuesDialog(void)
  1469. {    
  1470.     GrafPtr        savePort;
  1471.     DialogPtr    theDialog;
  1472.     Boolean        dialogDone = FALSE;
  1473.     short        itemHit;
  1474.  
  1475.     GetPort(&savePort);
  1476.     
  1477.     if ((theDialog = GetNewDialog(ANIMAL_POINT_VALUES_DIALOG, NULL, M_T_F)) == NULL)
  1478.     {
  1479.         ErrorHandler(NO_WIND);
  1480.     }
  1481.     CenterWindow(theDialog);
  1482.     ShowWindow(theDialog);
  1483.     
  1484.     SetPort(theDialog);
  1485.     
  1486.     while (!dialogDone)
  1487.     {
  1488.         ModalDialog(NULL, &itemHit);
  1489.         switch (itemHit - 1)
  1490.         {
  1491.             case RHINO:
  1492.             case ELEPHANT:
  1493.             case ZEBRA:
  1494.             case GORILLA:
  1495.             case ANTELOPE:
  1496.             case GIRAFFE:
  1497.             case LION:
  1498.             case CHEETAH:
  1499.             case WARTHOG:    
  1500.                 DoSound(BASE_RES_ID + itemHit - 1, TRUE);
  1501.                 break;
  1502.             case OK_APV_DBOX:
  1503.                 dialogDone = TRUE;
  1504.                 break;
  1505.             default:
  1506.                 break;
  1507.         }
  1508.     }
  1509.     DisposDialog(theDialog);
  1510.     SetPort(savePort);
  1511. }
  1512.  
  1513. AboutDialog(void)
  1514. {    
  1515.     GrafPtr     savePort;
  1516.     DialogPtr    theDialog;
  1517.     short            itemType;
  1518.     Handle        itemHandle;
  1519.     Rect        itemRect;
  1520.     Boolean        dialogDone = FALSE;
  1521.     short        itemHit;
  1522.     
  1523.     #define ICON_ITEM    5
  1524.  
  1525.     GetPort(&savePort);
  1526.     
  1527.     if ((theDialog = GetNewDialog(ABOUT_DIALOG, NULL, M_T_F)) == NULL)
  1528.     {
  1529.         ErrorHandler(NO_WIND);
  1530.     }
  1531.     CenterWindow(theDialog);
  1532.     ShowWindow(theDialog);
  1533.     
  1534.     SetPort(theDialog);
  1535.     
  1536.     GetDItem(theDialog, ICON_ITEM, &itemType, &itemHandle, &itemRect);
  1537.     PlotIcon(&itemRect, GetIcon(MY_HEAD));
  1538.     
  1539.     while (!dialogDone)
  1540.     {
  1541.         ModalDialog(NULL, &itemHit);
  1542.         switch (itemHit)
  1543.         {
  1544.             case OK_BUTTON:
  1545.                 dialogDone = TRUE;
  1546.                 break;
  1547.             case SHOW_INTRO_SCREEN:
  1548.                 IntroDialog();
  1549.                 break;
  1550.             case HEAD_ICON:
  1551.                 PlotIcon(&itemRect, GetIcon(OUCH_HEAD));
  1552.                 DoSound(OUCH_SOUND, FALSE);
  1553.                 PlotIcon(&itemRect, GetIcon(MY_HEAD));
  1554.                 break;
  1555.             default:
  1556.                 break;
  1557.         }
  1558.     }
  1559.     DisposDialog(theDialog);
  1560.     SetPort(savePort);
  1561. }
  1562.  
  1563. HallOfFameDialog(void)
  1564. {    
  1565.     GrafPtr         savePort;
  1566.     DialogPtr        theDialog;
  1567.     register int    i;
  1568.     StringHandle    theString;
  1569.     short            itemType;
  1570.     Handle            itemHandle;
  1571.     Rect            itemRect;
  1572.     Boolean         dialogDone = FALSE;
  1573.     short            itemHit;
  1574.     
  1575.     GetPort(&savePort);
  1576.     
  1577.     if ((theDialog = GetNewDialog(HALL_OF_FAME_DIALOG, NULL, M_T_F)) == NULL)
  1578.     {
  1579.         ErrorHandler(NO_WIND);
  1580.     }
  1581.     for (i = 0; i <= 5; i++)
  1582.     {
  1583.         if ((theString = GetString(128 + i)) == NULL)
  1584.         {
  1585.             ErrorHandler(NO_STR);
  1586.         }
  1587.         MoveHHi((Handle) theString);
  1588.         HLock((Handle) theString);    
  1589.         GetDItem(theDialog, i + 3, &itemType, &itemHandle, &itemRect);
  1590.         SetIText(itemHandle, *theString);
  1591.         HUnlock((Handle) theString);    
  1592.     }
  1593.     CenterWindow(theDialog);
  1594.     ShowWindow(theDialog);
  1595.     
  1596.     SetPort(theDialog);
  1597.     
  1598.     while (!dialogDone)
  1599.     {
  1600.         ModalDialog(NULL, &itemHit);
  1601.         switch (itemHit)
  1602.         {
  1603.             case OK_BUTTON:
  1604.                 dialogDone = TRUE;
  1605.                 break;
  1606.             case CLEAR_SCORES_BUTTON:
  1607.                 dialogDone = TRUE;
  1608.                 ClearHighScores();
  1609.                 break;
  1610.             default:
  1611.                 break;
  1612.         }
  1613.     }
  1614.     DisposDialog(theDialog);
  1615.     SetPort(savePort);
  1616. }
  1617.  
  1618. ClearHighScores(void)
  1619. {
  1620.     register int    i;
  1621.     StringHandle    theString;
  1622.     
  1623.     for (i = 0; i <= 2; i++)
  1624.     {
  1625.         if ((theString = GetString(HIGH_SCORE_STRING + i)) == NULL)
  1626.         {
  1627.             ErrorHandler(NO_STR);
  1628.         }
  1629.         HNoPurge((Handle) theString);
  1630.         SetString(theString, "\p0"); 
  1631.         ChangedResource((Handle) theString);
  1632.         WriteResource((Handle) theString);
  1633.         HPurge((Handle) theString);
  1634.         
  1635.         if ((theString = GetString(HIGH_NAMES_STRING + i)) == NULL)
  1636.         {
  1637.             ErrorHandler(NO_STR);
  1638.         }
  1639.         HNoPurge((Handle) theString);
  1640.         SetString(theString, "\pPlayer Name"); 
  1641.         ChangedResource((Handle) theString);
  1642.         WriteResource((Handle) theString);
  1643.         HPurge((Handle) theString);
  1644.         topScores[i] = 0;
  1645.     }
  1646. }
  1647.  
  1648. Boolean CheckITextValues(DialogPtr theDialog)
  1649. {
  1650.     register int    i;
  1651.     short            itemType;
  1652.     Handle            itemHandle;
  1653.     Rect            itemRect;
  1654.     long            stringValue;
  1655.     Boolean            dialogDone = TRUE;
  1656.     
  1657.     for (i = MINUTES; i <= MAX_ESCAPED; i++)
  1658.     {
  1659.         GetDItem(theDialog, i, &itemType, &itemHandle, &itemRect);
  1660.         MoveHHi((Handle) itemHandle);
  1661.         HLock(itemHandle);
  1662.         GetIText(itemHandle, preferenceString[i]);
  1663.         HUnlock(itemHandle);
  1664.     }
  1665.  
  1666.     StringToNum(preferenceString[MINUTES], &stringValue);
  1667.     if ((stringValue < 0) || (stringValue > 99))
  1668.     {
  1669.         BadValue(MINUTES_ERROR);
  1670.         SelIText(theDialog, MINUTES, 0, 255);
  1671.         dialogDone = FALSE;
  1672.     }
  1673.     
  1674.     StringToNum(preferenceString[SECONDS], &stringValue);
  1675.     if ((stringValue < 0) || (stringValue > 59))
  1676.     {
  1677.         BadValue(SECONDS_ERROR);
  1678.         SelIText(theDialog, SECONDS, 0, 255);
  1679.         dialogDone = FALSE;
  1680.     }
  1681.     
  1682.     StringToNum(preferenceString[MAX_ESCAPED], &stringValue);
  1683.     if ((stringValue < 1) || (stringValue > 99))
  1684.     {
  1685.         BadValue(ESCAPED_ERROR);
  1686.         SelIText(theDialog, MAX_ESCAPED, 0, 255);
  1687.         dialogDone = FALSE;
  1688.     }
  1689.     
  1690.     return (dialogDone);
  1691. }
  1692.  
  1693. CheckHighScoreDisplay(void)
  1694. {
  1695.     register int    i;
  1696.     StringHandle    theString;
  1697.     long            savedValues[8], preferenceValue[8];
  1698.     
  1699.     showHighScores = TRUE;
  1700.     
  1701.     for (i = 0; i <= 7; i++)
  1702.     {
  1703.         if ((theString = GetString(200 + i)) == NULL)
  1704.         {
  1705.             ErrorHandler(NO_STR);
  1706.         }
  1707.         MoveHHi((Handle) theString);
  1708.         HLock((Handle) theString);    
  1709.         StringToNum(*theString , &savedValues[i]);    
  1710.         HUnlock((Handle) theString);
  1711.         StringToNum(preferenceString[i], &preferenceValue[i]);
  1712.     }
  1713.     
  1714.     for (i = 0; i <= 4; i++)
  1715.     {
  1716.         if (savedValues[i] != preferenceValue[i])
  1717.         {
  1718.             showHighScores = FALSE;
  1719.         }
  1720.     }
  1721.  
  1722.     if (showHighScores)
  1723.     {
  1724.         switch (savedValues[TIMED_OR_ESCAPED - 200])
  1725.         {
  1726.             case TIMED_RADIO:
  1727.                 if (savedValues[MINUTES_STRING - 200] != preferenceValue[MINUTES_STRING - 200])
  1728.                 {
  1729.                     showHighScores = FALSE;
  1730.                 }
  1731.                 if (savedValues[SECONDS_STRING - 200] != preferenceValue[SECONDS_STRING - 200])
  1732.                 {
  1733.                     showHighScores = FALSE;
  1734.                 }
  1735.                 break;
  1736.             case ESCAPED_RADIO:
  1737.                 if (savedValues[MAX_ESCAPED_STRING - 200] != preferenceValue[MAX_ESCAPED_STRING - 200])
  1738.                 {
  1739.                     showHighScores = FALSE;
  1740.                 }
  1741.                 break;
  1742.             default:
  1743.                 break;
  1744.         }    
  1745.     }
  1746.     
  1747.     if (showHighScores)
  1748.     {
  1749.         GetHighScores();
  1750.     }
  1751. }
  1752.  
  1753. GameOptionsDialog(void)
  1754. {
  1755.     GrafPtr        savePort;
  1756.     DialogPtr    theDialog;
  1757.     Boolean        dialogDone = FALSE;
  1758.     short        itemHit;
  1759.     short        itemType;
  1760.     Handle        itemHandle;
  1761.     Rect        itemRect;
  1762.  
  1763.     GetPort(&savePort);
  1764.  
  1765.     if ((theDialog = GetNewDialog(GAME_OPTIONS_DIALOG, NULL, M_T_F)) == NULL)
  1766.     {
  1767.         ErrorHandler(NO_WIND);
  1768.     }
  1769.     DialogInit(theDialog);
  1770.     CenterWindow(theDialog);
  1771.     ShowWindow(theDialog);
  1772.     
  1773.     while (!dialogDone)
  1774.     {
  1775.         ModalDialog((ModalFilterUPP) &GameOptionsDProc, &itemHit);
  1776.         switch (itemHit)
  1777.         {
  1778.             case OK_BUTTON:
  1779.                 dialogDone = CheckITextValues(theDialog);
  1780.                 if (dialogDone)
  1781.                 {
  1782.                     showHighScores = FALSE;
  1783.                     CheckHighScoreDisplay();
  1784.                     SetUpGame();
  1785.                 }
  1786.                 break;
  1787.             case SAVE_AND_CLEAR_BUTTON:
  1788.                 dialogDone = CheckITextValues(theDialog);
  1789.                 if (dialogDone)
  1790.                 {
  1791.                     UpdatePreferences(theDialog);    
  1792.                     ClearHighScores();
  1793.                     showHighScores = TRUE;
  1794.                     SetUpGame();
  1795.                 }
  1796.                 break;
  1797.             case CANCEL_BUTTON:
  1798.                 dialogDone = TRUE;
  1799.                 break;
  1800.             case TIMED_RADIO:
  1801.             case ESCAPED_RADIO:
  1802.                 GetDItem(theDialog, TIMED_RADIO, &itemType, &itemHandle, &itemRect);
  1803.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == TIMED_RADIO));
  1804.                 GetDItem(theDialog, ESCAPED_RADIO, &itemType, &itemHandle, &itemRect);
  1805.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == ESCAPED_RADIO));
  1806.                 NumToString(itemHit, preferenceString[TIMED_OR_ESCAPED - 200]);
  1807.                 break;
  1808.             case SPEED_POP_UP:
  1809.                 GetDItem(theDialog, SPEED_POP_UP, &itemType, &itemHandle, &itemRect);
  1810.                 itemHit = GetCtlValue((ControlHandle) itemHandle);
  1811.                 NumToString(itemHit + 24, preferenceString[ANIMAL_SPEED - 200]);
  1812.                 break;
  1813.             case NINE_INCH_RADIO:
  1814.             case CURRENT_SCREEN_RADIO:
  1815.                 GetDItem(theDialog, NINE_INCH_RADIO, &itemType, &itemHandle, &itemRect);
  1816.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == NINE_INCH_RADIO));
  1817.                 GetDItem(theDialog, CURRENT_SCREEN_RADIO, &itemType, &itemHandle, &itemRect);
  1818.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == CURRENT_SCREEN_RADIO));
  1819.                 NumToString(itemHit, preferenceString[WINDOW_SIZE - 200]);
  1820.                 break;
  1821.             case INCREASE_YES_RADIO:
  1822.             case INCREASE_NO_RADIO:
  1823.                 GetDItem(theDialog, INCREASE_YES_RADIO, &itemType, &itemHandle, &itemRect);
  1824.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == INCREASE_YES_RADIO));
  1825.                 GetDItem(theDialog, INCREASE_NO_RADIO, &itemType, &itemHandle, &itemRect);
  1826.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == INCREASE_NO_RADIO));
  1827.                 NumToString(itemHit, preferenceString[INCREASE_SPEED - 200]);
  1828.                 break;
  1829.             case IN_ANIMAL_OUTLINE_RADIO:
  1830.             case IN_BOX_SURROUNDING_ANIMAL_RADIO:
  1831.                 GetDItem(theDialog, IN_ANIMAL_OUTLINE_RADIO, &itemType, &itemHandle, &itemRect);
  1832.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == IN_ANIMAL_OUTLINE_RADIO));
  1833.                 GetDItem(theDialog, IN_BOX_SURROUNDING_ANIMAL_RADIO, &itemType, &itemHandle, &itemRect);
  1834.                 SetCtlValue((ControlHandle) itemHandle, (itemHit == IN_BOX_SURROUNDING_ANIMAL_RADIO));
  1835.                 NumToString(itemHit, preferenceString[SCORE_WHEN_HIT - 200]);
  1836.                 break;
  1837.             default:
  1838.                 break;
  1839.         }
  1840.     }
  1841.     
  1842.     DisposDialog(theDialog);
  1843.     SetPort(savePort);
  1844. }
  1845.  
  1846. pascal Boolean GameOptionsDProc(DialogPtr theDialog, EventRecord *theEvent, int *itemHit)
  1847. {
  1848.     short        itemType;
  1849.     Handle        itemHandle;
  1850.     Rect        itemRect;
  1851.  
  1852.     switch (theEvent->what)
  1853.     {
  1854.         case updateEvt:
  1855.             if (IsDialogEvent(theEvent))
  1856.             {
  1857.                 SetPort(theDialog);
  1858.                 GetDItem(theDialog, 25, &itemType, &itemHandle, &itemRect);
  1859.                 FrameRect(&itemRect);
  1860.                 GetDItem(theDialog, 26, &itemType, &itemHandle, &itemRect);
  1861.                 FrameRect(&itemRect);
  1862.                 GetDItem(theDialog, 27, &itemType, &itemHandle, &itemRect);
  1863.                 FrameRect(&itemRect);
  1864.             }
  1865.             return (FALSE);
  1866.             break;
  1867.         default:
  1868.             return (FALSE);
  1869.             break;
  1870.     }
  1871. }
  1872.  
  1873. UpdatePreferences(DialogPtr theDialog)
  1874. {
  1875.     register int    i;
  1876.     StringHandle    theString;
  1877.     
  1878.     for (i = 200; i <= 214; i += (i == 204) ? 8 : 1)
  1879.     {
  1880.         if ((theString = GetString(i)) == NULL)
  1881.         {
  1882.             ErrorHandler(NO_STR);
  1883.         }
  1884.         HNoPurge((Handle) theString);
  1885.         SetString(theString, preferenceString[i - 200]); 
  1886.         ChangedResource((Handle) theString);
  1887.         WriteResource((Handle) theString);
  1888.         HPurge((Handle) theString);
  1889.     }
  1890. }
  1891.  
  1892. DialogInit(DialogPtr theDialog)
  1893. {
  1894.     register int    i;
  1895.     StringHandle    theString;
  1896.     long            itemNumber;
  1897.     short            itemType;
  1898.     Handle            itemHandle;
  1899.     Rect            itemRect;
  1900.  
  1901.     for (i = TIMED_OR_ESCAPED; i <= SCORE_WHEN_HIT; i++)
  1902.     {
  1903.         if ((theString = GetString(i)) == NULL)
  1904.         {
  1905.             ErrorHandler(NO_STR);
  1906.         }
  1907.         MoveHHi((Handle) theString);
  1908.         HLock((Handle) theString);    
  1909.         StringToNum(*theString, &itemNumber);
  1910.         if ((itemNumber == SLOW_RADIO) || (itemNumber == MEDIUM_RADIO) || 
  1911.             (itemNumber == FAST_RADIO))
  1912.         {
  1913.             GetDItem(theDialog, SPEED_POP_UP, &itemType, &itemHandle, &itemRect);
  1914.             SetCtlValue((ControlHandle) itemHandle, itemNumber - 24);
  1915.         }
  1916.         else
  1917.         {
  1918.             GetDItem(theDialog, itemNumber, &itemType, &itemHandle, &itemRect);
  1919.             SetCtlValue((ControlHandle) itemHandle, TRUE);
  1920.         }
  1921.         NumToString(itemNumber, preferenceString[i - 200]);
  1922.         HUnlock((Handle) theString);
  1923.     }
  1924.  
  1925.     for (i = MINUTES_STRING; i <= MAX_ESCAPED_STRING; i++)
  1926.     {
  1927.         if ((theString = GetString(i)) == NULL)
  1928.         {
  1929.             ErrorHandler(NO_STR);
  1930.         }
  1931.         MoveHHi((Handle) theString);
  1932.         HLock((Handle) theString);    
  1933.         GetDItem(theDialog, i - 200, &itemType, &itemHandle, &itemRect);
  1934.         SetIText(itemHandle, *theString);
  1935. /*
  1936.         item number is just a place holder in the next two lines (it's significant
  1937.         as the item number in all other code) I couldn't get the string handle
  1938.         to equate to the string, so this is my work around. I make the string
  1939.         handle a number, then make the number a string.  Ugly but functional.
  1940. */
  1941.         StringToNum(*theString, &itemNumber);
  1942.         NumToString(itemNumber, preferenceString[i - 200]);
  1943.         HUnlock((Handle) theString);
  1944.     }
  1945. }
  1946.  
  1947. BadValue(int stringNum)
  1948. {
  1949.     StringHandle    errorStringH;
  1950.     
  1951.     if ((errorStringH = GetString(stringNum)) == NULL)
  1952.     {
  1953.         ParamText(HOPELESSLY_FATAL_ERROR, NULL, NULL, NULL);
  1954.     }
  1955.     else
  1956.     {
  1957.         MoveHHi((Handle) errorStringH);
  1958.         HLock((Handle) errorStringH);
  1959.         ParamText(*errorStringH, NULL, NULL, NULL);
  1960.         HUnlock((Handle) errorStringH);
  1961.     }
  1962.     StopAlert(ERROR_EDIT_TEXT, NULL);
  1963. }
  1964.  
  1965. IntroDialog(void)
  1966. {
  1967.     GrafPtr        savePort;
  1968.     DialogPtr    theDialog;
  1969.     Rect        dialogRect, clippingRect;
  1970.     GrafPtr        dLogOffscreen;
  1971.     int            itemHit, i, beginTicks, currentTicks, h;
  1972.  
  1973.     GetPort(&savePort);
  1974.  
  1975.     if ((theDialog = GetNewDialog(INTRO_DIALOG, NULL, M_T_F)) == NULL)
  1976.     {
  1977.         ErrorHandler(NO_WIND);
  1978.     }
  1979.     CenterWindow(theDialog);
  1980.     ShowWindow(theDialog);
  1981.     
  1982.     SetPort(theDialog);
  1983.  
  1984.     dialogRect = theDialog->portRect;
  1985.     if (!CreateOffscreenBitMap(&dLogOffscreen, &dialogRect)) 
  1986.     {
  1987.         SysBeep(1);
  1988.         ExitToShell();
  1989.     }
  1990.     
  1991.     SetPort(dLogOffscreen);
  1992.     
  1993.     DrawPicture(GetPicture(475), &dialogRect);
  1994.   
  1995.     SetPort(theDialog);
  1996.     
  1997.     DoSound(INTRO_SOUND, TRUE);
  1998.     
  1999.     h = (dialogRect.bottom - dialogRect.top) / 2;
  2000.     
  2001.     SetRect(&clippingRect, dialogRect.left, h, dialogRect.right, h);
  2002.     for (i = 1; i <= h + 1; i += 4)
  2003.     {
  2004.         ClipRect(&clippingRect);
  2005.         clippingRect.top -= 4;
  2006.         clippingRect.bottom += 4;
  2007.         CopyBits(&dLogOffscreen->portBits, &theDialog->portBits,
  2008.             &dialogRect, &dialogRect, srcCopy, NULL);            
  2009.         beginTicks = TickCount();
  2010.         do
  2011.         {
  2012.             currentTicks = TickCount();
  2013.         }
  2014.         while ((currentTicks - beginTicks) <= 2);
  2015.     }
  2016.     
  2017.     while (!Button());
  2018.     
  2019.     DisposDialog(theDialog);
  2020.     SetPort(savePort);
  2021. }
  2022.